package com.sf.business.audit.service.impl;

import com.sf.business.appointment.controller.BusAppointmentController;
import com.sf.business.appointment.domain.BusServiceItem;
import com.sf.business.appointment.mapper.BusServiceItemMapper;
import com.sf.business.audit.domain.BusCarPackageInfo;
import com.sf.business.audit.mapper.BusCarPackageInfoMapper;
import com.sf.business.audit.qo.BusCarPackageHistoryInfo;
import com.sf.business.audit.service.IBusCarPackageInfoService;
import com.sf.business.audit.vo.BusCarPackageAuditResultVO;
import com.sf.business.process.domain.BusBpmnInfo;
import com.sf.business.process.mapper.BusBpmnInfoMapper;
import com.sf.common.utils.DateUtils;
import com.sf.common.utils.SecurityUtils;
import io.jsonwebtoken.lang.Assert;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.util.*;

import static com.sf.common.utils.PageUtils.startPage;

/**
 * 套餐信息Service业务层处理
 *
 * @author lh
 * @date 2025-03-30
 */
@Service
public class BusCarPackageInfoServiceImpl implements IBusCarPackageInfoService {
    @Autowired
    private BusCarPackageInfoMapper busCarPackageInfoMapper;
    @Autowired
    private BusBpmnInfoMapper busBpmnInfoMapper;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private BusAppointmentController busAppointmentController;
    @Autowired
    private BusServiceItemMapper busServiceItemMapper;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;

    /**
     * 查询套餐信息
     *
     * @param id 套餐信息主键
     * @return 套餐信息
     */
    @Override
    public BusCarPackageInfo selectBusCarPackageInfoById(Long id) {
        return busCarPackageInfoMapper.selectBusCarPackageInfoById(id);
    }

    /**
     * 查询套餐信息列表
     *
     * @param busCarPackageInfo 套餐信息
     * @return 套餐信息
     */
    @Override
    public List<BusCarPackageInfo> selectBusCarPackageInfoList(BusCarPackageInfo busCarPackageInfo) {
        busCarPackageInfo.setCreatorId(String.valueOf(SecurityUtils.getUserId()));
        return busCarPackageInfoMapper.selectBusCarPackageInfoList(busCarPackageInfo);
    }

    /**
     * 新增套餐信息
     *
     * @param busCarPackageInfo 套餐信息
     * @return 结果
     */
    @Override
    public int insertBusCarPackageInfo(BusCarPackageInfo busCarPackageInfo) {
        busCarPackageInfo.setCreateTime(DateUtils.getNowDate());
        return busCarPackageInfoMapper.insertBusCarPackageInfo(busCarPackageInfo);
    }

    /**
     * 修改套餐信息
     *
     * @param busCarPackageInfo 套餐信息
     * @return 结果
     */
    @Override
    public int updateBusCarPackageInfo(BusCarPackageInfo busCarPackageInfo) {
        return busCarPackageInfoMapper.updateBusCarPackageInfo(busCarPackageInfo);
    }

    /**
     * 批量删除套餐信息
     *
     * @param ids 需要删除的套餐信息主键
     * @return 结果
     */
    @Override
    public int deleteBusCarPackageInfoByIds(Long[] ids) {
        return busCarPackageInfoMapper.deleteBusCarPackageInfoByIds(ids);
    }

    /**
     * 删除套餐信息信息
     *
     * @param id 套餐信息主键
     * @return 结果
     */
    @Override
    public int deleteBusCarPackageInfoById(Long id) {
        return busCarPackageInfoMapper.deleteBusCarPackageInfoById(id);
    }

    @Override
    public InputStream queryProcess(Long id) {
        // 1. 数据库中查找数据, 并验证非空
        BusCarPackageInfo busCarPackageInfo = busCarPackageInfoMapper.selectBusCarPackageInfoById(id);
        Assert.notNull(busCarPackageInfo, "数据库中不存在相关数据");

        // 2. 查阅最新版本的 bpmnInfo 信息, 并校验非空
        BusBpmnInfo busBpmnInfo = busBpmnInfoMapper.selectBpmnInfoLastVersion();
        Assert.notNull(busBpmnInfo, "没有相关 bpmnInfo 信息");

        // 3. 判断状态是否 [审核中], 是获取高亮结点集合, 否返回空集合
        List<String> activeActivityIds = new ArrayList<>();
        if (busCarPackageInfo.getStatus().equals(BusCarPackageInfo.STATUS_AUDITING)) {
            activeActivityIds = runtimeService.getActiveActivityIds(busCarPackageInfo.getInstanceId());
        } else {
            activeActivityIds = Collections.emptyList();
        }

        // 4. 调用工具类进行绘图
        DefaultProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(busBpmnInfo.getProcessDefinitionKey())
                .processDefinitionVersion(busBpmnInfo.getVersion().intValue())
                .singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
        /**
         * 第一个参数: 流程定义模型
         * 第二个参数: 高亮节点集合
         * 第三个参数: 高亮连线集合
         */
        InputStream inputStream = processDiagramGenerator.generateDiagram(
                bpmnModel,
                activeActivityIds,
                Collections.emptyList(),
                "宋体",
                "宋体",
                "宋体");

        return inputStream;
    }

    @Override
    @Transactional
    public void cancel(Long id) {
        // 1. bus_car_package_audit 查数据, 判空
        BusCarPackageInfo busCarPackageInfo = busCarPackageInfoMapper.selectBusCarPackageInfoById(id);
        Assert.notNull(busCarPackageInfo, "数据库中不存在相关数据");

        // 2. 判断状态是否审核中
        if (!busCarPackageInfo.getStatus().equals(BusCarPackageInfo.STATUS_AUDITING))
            throw new IllegalArgumentException("状态不正确, 需要 [审核中 0]");

        // 3. 将状态改为 [审核撤销]
        busCarPackageInfo.setStatus(BusCarPackageInfo.STATUS_AUDIT_CANCEL);

        // 4. 修改服务项状态: 从 [审核中 1] 修改为 [初始化 0]
        BusServiceItem busServiceItem = busServiceItemMapper.selectBusServiceItemById(busCarPackageInfo.getServiceItemId());
        Assert.notNull(busServiceItem, "数据库中不存在相关 服务项 数据");
        if (!busServiceItem.getAuditStatus().equals(BusServiceItem.AUDIT_STATUS_AUDITING))
            throw new IllegalArgumentException("服务项状态出现问题, 需要 [审核中]");

        busServiceItem.setAuditStatus(BusServiceItem.AUDIT_STATUS_INITIALIZE);

        // 5. 删除 对应的流程实例
        runtimeService.deleteProcessInstance(busCarPackageInfo.getInstanceId(), "审核撤销");

        busCarPackageInfoMapper.updateBusCarPackageInfo(busCarPackageInfo);
        busServiceItemMapper.updateBusServiceItem(busServiceItem);
    }

    @Override
    public List<BusCarPackageInfo> todo() {
        // 1. 查询最新的服务套餐 bpmnInfo 信息
        BusBpmnInfo busBpmnInfo = busBpmnInfoMapper.selectBpmnInfoLastVersion();
        Assert.notNull(busBpmnInfo, "套餐审核流程信息不存在");

        // 2 获取流程定义的 key
        String processDefinitionKey = busBpmnInfo.getProcessDefinitionKey();

        // 3. 根据流程定义 key 获取  任务表信息 List<Task> taskList
        List<Task> taskList = taskService.createTaskQuery()
                .processDefinitionKey(processDefinitionKey)
                .taskAssignee(SecurityUtils.getUserId().toString())
                .list();

        // 4. 遍历任务集合, 收集 businessKey (bus_car_package_audit 表的 id)
        List<Long> businessKeys = new ArrayList<>();

        for (Task task : taskList) {
            // 5. 根据任务获取流程实例信息
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(task.getProcessInstanceId())
                    .singleResult();

            // 6. 获取对应的 businessKey
            String businessKey = processInstance.getBusinessKey();

            // 7. 将 businessKey 添加到 List<Long> businessKeys 中
            businessKeys.add(Long.parseLong(businessKey));
        }

        // 8. 如果 businessKeys 为空, 返回空集合, 否返回数据
        if (businessKeys.isEmpty())
            return Collections.emptyList();

        startPage();
        List<BusCarPackageInfo> busCarPackageInfos = busCarPackageInfoMapper.selectBusCarPackageInfoByIds(businessKeys);

        return busCarPackageInfos;
    }

    /**
     * 审核通过
     * 1. 流程前进, 如果有下一个结点, 则继续执行, 否结束流程;
     * 没有下一个结点, 流程结束, 修改 bus_service_item 表状态为 [审核通过]
     * 2. bus_car_package_audit 修改状态为 [审核通过]
     * 审核拒绝
     * 1. 流程结束, 修改 bus_service_item, bus_car_package_audit 表状态为 [审核拒绝]
     */
    @Override
    @Transactional
    public void audit(BusCarPackageAuditResultVO vo) {
        // 0. 参数校验
        Assert.notNull(vo.getId(), "参数 id 不能为空");
        Boolean auditStatus = vo.getAuditStatus();
        Assert.notNull(auditStatus, "参数 auditStatus 不能为空");

        // 1. 根据 id 查询 bus_car_package_audit 表数据, 判空
        BusCarPackageInfo busCarPackageInfo = busCarPackageInfoMapper.selectBusCarPackageInfoById(vo.getId());
        Assert.notNull(busCarPackageInfo, "数据库中不存在相关数据");

        // 2. 判读状态是否为 [审核中]
        Assert.isTrue(busCarPackageInfo.getStatus().equals(BusCarPackageInfo.STATUS_AUDITING), "状态不正确, 需要 [审核中 0]");

        // 3. 获取流程实例id
        String processInstanceId = busCarPackageInfo.getInstanceId();

        // 4. 查询当前任务结点
        Task task = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)
                .singleResult();

        // 5. 执行流程
        // 5.1. 设置流程变量 shopOwner 为 auditStatus
        Map<String, Object> map = new HashMap<>();
        map.put("shopOwner", auditStatus);

        // 5.2. 设置批注
        String message = "";
        if (auditStatus)
            message = "审核通过";
        else
            message = "审核拒绝";
        message += ", 审核意见为:  " + vo.getInfo();
        taskService.addComment(task.getId(), processInstanceId, message);
        taskService.complete(task.getId(), map);

        // 6. 判断审批同意还是拒绝
        if (auditStatus) {
            // 6.1. 同意
            // 6.1.1. 再次查看 act_ru_task 表, 根据是否有信息判断是否流程未结束
            Task taskNext = taskService.createTaskQuery()
                    .processInstanceId(processInstanceId)
                    .singleResult();
            if (taskNext == null) {
                // 6.1.1.1. 没有任务, 流程结束, 将 bus_service_item 表状态改为 [审核通过], 将 bus_car_package_audit 表状态改为 [审核通过]
                busServiceItemMapper.updateBusServiceItem(new BusServiceItem(busCarPackageInfo.getServiceItemId(), BusServiceItem.AUDIT_STATUS_AUDIT_PASS));
                busCarPackageInfo.setStatus(BusCarPackageInfo.STATUS_AUDIT_PASS);
            }
        } else {
            // 6.2. 拒绝, 直接将 bus_car_package_audit 表状态改为 [审核拒绝], bus_service_item 表设置为 [重新调整]
            busCarPackageInfo.setStatus(BusCarPackageInfo.STATUS_AUDIT_REFUSE);
            busServiceItemMapper.updateBusServiceItem(new BusServiceItem(busCarPackageInfo.getServiceItemId(), BusServiceItem.AUDIT_STATUS_READJUST));
        }
        busCarPackageInfoMapper.updateBusCarPackageInfo(busCarPackageInfo);
    }

    @Override
    public List<BusCarPackageHistoryInfo> selectHistoryInfoById(String id) {
        List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
//                .taskAssignee(SecurityUtils.getUserId().toString())
                .processInstanceId(id)
                .finished()
                .list();
        Assert.notNull(historicTaskInstances, "流程实例不存在");

//        historyService.createHistoricCommentQuery

        List<BusCarPackageHistoryInfo> list = new ArrayList<>();

        for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) {
            List<Comment> taskComments = taskService.getTaskComments(historicTaskInstance.getId());
            if (taskComments.isEmpty())
                continue;

            BusCarPackageHistoryInfo busCarPackageHistoryInfo = new BusCarPackageHistoryInfo(
                    historicTaskInstance.getName(),
                    historicTaskInstance.getStartTime(),
                    historicTaskInstance.getEndTime(),
                    historicTaskInstance.getDurationInMillis()/1000 + " s",
                    taskComments.get(0).getFullMessage()
            );
            list.add(busCarPackageHistoryInfo);
        }

        return list;
    }

    @Override
    public List<BusCarPackageInfo> done() {
        // 1. 查询最新的 服务套餐信息
        BusBpmnInfo busBpmnInfo = busBpmnInfoMapper.selectBpmnInfoLastVersion();
        Assert.notNull(busBpmnInfo, "套餐审核流程信息不存在");

        // 2. 获取流程定义的 Key
        String processDefinitionKey = busBpmnInfo.getProcessDefinitionKey();

        // 3. 查询已完成的流程实例
        List<HistoricProcessInstance> historicProcessInstances = historyService.createHistoricProcessInstanceQuery()
                .processDefinitionKey(processDefinitionKey)
                .finished()
                .list();

        // 4. 获取对应的 businessKey (套餐信息id)
        List<Long> businessKeys = new ArrayList<>();
        for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
            String businessKey = historicProcessInstance.getBusinessKey();
            businessKeys.add(Long.valueOf(businessKey));
        }

        if (businessKeys.isEmpty())
            return Collections.emptyList();

        startPage();
        List<BusCarPackageInfo> busCarPackageInfos = busCarPackageInfoMapper.selectHistoryCarPackageInfoByIds(businessKeys);

        return busCarPackageInfos;
    }
}
